package com.xg.te.core;

import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xg.te.core.bean.WebsiteBean;
import com.xg.te.core.bean.EngineBean;
import com.xg.te.core.bean.IncludeBean;
import com.xg.te.core.bean.PageBean;
import com.xg.te.core.bean.PageReference;
import com.xg.te.plugin.PluginStore;
import com.xg.te.plugin.bean.PluginBean;
import com.xg.te.strategy.Strategy;
import com.xg.te.strategy.StrategyProxy;
import com.xg.te.strategy.StrategyStore;
import com.xg.te.strategy.bean.StrategyBean;
import com.xg.te.strategy.bean.StrategyReference;
import com.xg.te.util.ReflectionUtils;
import com.xg.te.util.XmlUtils;

/**
 * 模板引擎
 * 
 * @author liuguojun
 * @date 2014-06-09
 */
public class Start {

	private static final Logger logger = Logger.getLogger(Start.class);

	public static final String ENGINE_PATH = "engine.xml";

	private static Map<String, Set<String>> cache = new HashMap<String, Set<String>>();

	private String baseFolder = "";

	/**
	 * 构造函数
	 */
	public Start() {
		URL url = getClass().getClassLoader().getResource(ENGINE_PATH);
		if (url != null) {
			String filePath = url.getPath();
			if (filePath.indexOf("%20") > -1) {
				filePath = filePath.replace("%20", " ");
			}
			init(filePath);
		} else {
			logger.info(ENGINE_PATH + "未被程序发现,程序未能初始化");
		}
	}

	/**
	 * 构造函数
	 * 
	 * @param filePath
	 * @throws Exception
	 */
	public Start(String filePath) {
		init(filePath);
	}

	/**
	 * 初始化方法
	 * 
	 * @throws Exception
	 */
	private void init(String filePath) {
		try {
			baseFolder = filePath.replace(ENGINE_PATH, "");
			logger.info("classDir=" + baseFolder);

			init(new File(baseFolder + ENGINE_PATH));

			iterateWebsite(WebsiteStore.values());

			executeStrategy();
		} catch (Exception ex) {
			logger.error(ex.getMessage(), ex);
		}
	}

	/**
	 * 初始化方法
	 * 
	 * @throws Exception
	 */
	private void init(File file) throws Exception {
		EngineBean engine = XmlUtils.getInstance().parseXml(file);
		if (null != engine) {
			// 缓存页面
			cachePage(engine.getPages());
			// 缓存功能插件
			cachePlugin(engine.getPlugins());
			// 缓存代理插件
			cacheWebsite(engine.getWebsites());
			// 缓存策略
			cacheStrategy(engine.getStrategies());

			List<IncludeBean> includes = engine.getIncludes();
			if (includes != null) {
				for (int i = 0; i < includes.size(); i++) {
					IncludeBean include = includes.get(i);
					init(new File(baseFolder + include.getFile()));
				}
			}
		}
	}

	/**
	 * 缓存页面
	 * 
	 * @param pages
	 */
	private void cachePage(List<PageBean> pages) {
		if (pages != null) {
			Iterator<PageBean> it = pages.iterator();
			while (it.hasNext()) {
				PageBean page = it.next();
				PageStore.put(page.getCode(), page);
			}
		}
	}

	/**
	 * 缓存功能插件
	 * 
	 * @param plugins
	 */
	private void cachePlugin(List<PluginBean> plugins) {
		if (plugins != null) {
			Iterator<PluginBean> it = plugins.iterator();
			while (it.hasNext()) {
				PluginBean plugin = it.next();
				PluginStore.put(plugin.getCode(), plugin);
			}
		}
	}

	/**
	 * 缓存站点
	 * 
	 * @param websites
	 * @throws Exception
	 */
	private void cacheWebsite(List<WebsiteBean> websites) throws Exception {
		if (websites != null) {
			Iterator<WebsiteBean> it = websites.iterator();
			while (it.hasNext()) {
				WebsiteBean website = it.next();
				WebsiteStore.put(website);
			}
		}
	}

	/**
	 * 缓存策略
	 * 
	 * @param strategies
	 */
	private void cacheStrategy(List<StrategyBean> strategies) {
		if (strategies != null) {
			Iterator<StrategyBean> it = strategies.iterator();
			while (it.hasNext()) {
				StrategyBean sb = it.next();
				StrategyStore.put(sb.getCode(), sb);
			}
		}
	}

	/**
	 * 遍历代理商
	 * 
	 * @param websites
	 * @throws Exception
	 */
	private void iterateWebsite(Collection<WebsiteBean> websites) throws Exception {
		Iterator<WebsiteBean> it = websites.iterator();
		while (it.hasNext()) {
			WebsiteBean website = it.next();
			iteratePage(website, website.getPages());
		}
	}

	/**
	 * 遍历页面模板
	 * 
	 * @param pages
	 * @throws Exception
	 */
	private void iteratePage(WebsiteBean website, List<PageReference> pages)
			throws Exception {
		String websiteCode = website.getConstantValue("code");

		// 设置页面参数
		for (Iterator<PageReference> it = pages.iterator(); it.hasNext();) {
			PageReference pr = it.next();
			String pageCode = pr.getCode();

			/* 查询页面对象 */
			PageBean page = PageStore.get(pageCode);
			if (page == null) {
				logger.error("(" + pageCode + ")page not exists",
						new Exception("(" + pageCode + ")page not exists"));
				continue;
			}
			String hpath = page.getHpath();
			/* 将页面地址添加到公用参数缓存中 */
			ParamStore.put("page_" + pageCode, hpath);

			/* 查询页面生产策略 */
			List<StrategyReference> strategies = page.getStrategies();
			if (strategies == null) {
				continue;
			}
			for (Iterator<StrategyReference> its = strategies.iterator(); its
					.hasNext();) {
				StrategyReference sr = its.next();
				String strategyCode = sr.getCode();
				
				/* 获取策略下的页面集合，并将当前页面加入其中 */
				Set<String> set = cache.get(strategyCode);
				if (set == null) {
					set = new HashSet<String>();
				}
				set.add(websiteCode + "_" + pageCode);
				cache.put(strategyCode, set);
			}
		}
	}

	/**
	 * 执行策略
	 */
	public void executeStrategy() {
		Set<String> keys = cache.keySet();
		for (Iterator<String> it = keys.iterator(); it.hasNext();) {
			String strategyCode = it.next();

			StrategyBean sb = StrategyStore.get(strategyCode);
			if (sb == null) {
				logger.info("请检查策略配置文件," + strategyCode + "不存在");
				continue;
			}

			Set<String> pages = cache.get(strategyCode);

			String bean = sb.getBean();
			String args = sb.getArgs();

			Object strategy = null;
			if ("spring".equals(sb.getInit())) {
				// strategy = SpringUtils.getBean(bean);
			} else if ("instance".equals(sb.getInit())) {
				strategy = ReflectionUtils.newInstance(bean);
			}

			// 验证插件是否实例化
			if (strategy == null) {
				logger.info("strategy(code=" + strategyCode + ", bean=" + bean
						+ ")不能正常实例化");
				continue;
			}

			// 验证是否是插件
			if (!(strategy instanceof Strategy)) {
				logger.info("strategy(code=" + strategyCode + ", bean=" + bean
						+ ")未继承 " + Strategy.class.getName() + "类");
				continue;
			}

			JSONObject jsonObj = null;
			if (args != null && !"".equals(args)) {
				jsonObj = JSON.parseObject(args);
			}
			Strategy s = (Strategy) strategy;
			s.addPages(pages);
			StrategyProxy.proxyExecute(s, jsonObj);
		}
	}

	public static void main(String[] args) {
		new Start();
	}
}
